package com.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.ObjectMetadata;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.common.constant.MailConstant;
import com.common.constant.SharesConstan;
import com.common.constant.UpLoadConstant;
import com.common.utils.*;
import com.entity.*;
import com.mapper.CodeCjlMapper;
import com.service.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.hc.client5.http.classic.methods.HttpGet;
import org.apache.hc.client5.http.impl.classic.CloseableHttpResponse;
import org.apache.hc.core5.http.io.entity.EntityUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import sun.misc.BASE64Decoder;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author pumpkin
 * @since 2021-10-22
 */
@Service
public class CodeCjlServiceImpl extends ServiceImpl<CodeCjlMapper, CodeCjl> implements CodeCjlService {

    @Autowired
    private SharesInformService sharesInformService;

    @Autowired
    private UserMailService userMailService;

    @Autowired
    private HintSharesService hintSharesService;

    @Autowired
    private MailUtil mailUtil;



    public static int  order=0;

    @Override
    public List<CodeCjl> getCodeCjls(List<CodeCjl> list) {
        List<CodeCjl> codeCjls=new ArrayList<>();

        int listSize=list.size();
        int toIndex=50;
        int keyToken = 0;
        for(int i = 0;i<list.size();i+=50) {
            if(i+50>listSize){        //作用为toIndex最后没有50条数据则剩余几条newList中就装几条
                toIndex=listSize-i;
            }
            List<CodeCjl> newList = list.subList(i,i+toIndex);

            StringBuffer sb=new StringBuffer();
            if(!CollectionUtils.isEmpty(newList)){
                for (CodeCjl code : newList) {
                    sb.append(code.getCode()+",");
                }
            }

            String urlstring = sb.toString().substring(0, sb.toString().length() - 1);

            //发送请求得到数据
            String data="";
            try {
                HttpGet httpGet=new HttpGet("http://hq.sinajs.cn/list="+urlstring);
//                data = HttpUtil.sendGet("http://hq.sinajs.cn/list=" + urlstring, null);
//                HttpGet httpGet=new HttpUtil();
                CloseableHttpResponse execute = HttpClient5Utils.httpclient
                        .execute(httpGet);
                data = EntityUtils.toString(execute.getEntity());
            } catch (Exception e) {
                e.printStackTrace();
            }

            if(StringUtils.isEmpty(data)){
                return null;
            }
            String[] split = data.split(";\n");
//            格式数据：
//            var hq_str_sz000029="深深房Ａ,7.360,7.440,7.510,7.510,7.340,7.500,7.510,2379200,17684038.000,12600,7.500,5800,7.490,9100,7.480,9800,7.470,30900,7.460,4100,7.510,21000,7.520,6800,7.530,12400,7.540,27200,7.550,2021-03-04,09:52:03,00";
//            var hq_str_sh603986="兆易创新,197.150,199.000,196.500,200.710,196.330,196.510,196.600,1295825,257338818.000,800,196.510,1800,196.500,500,196.490,3400,196.480,300,196.470,100,196.600,2800,196.610,100,196.690,800,196.700,900,196.710,2021-03-04,09:52:03,00,";
            for (String vo : split) {
                String[] splitvo = vo.split(",");
                String[] splitCode = splitvo[0].split("=");//var hq_str_sz000029="深深房Ａ
                String codeStr = splitCode[0];
                String code = codeStr.substring(codeStr.length() - 6);
                if(splitvo.length<2){
                    continue;
                }
                String startPrice=splitvo[1];//开盘价
                String endprice=splitvo[2];//开盘价
                String nowPrice=splitvo[3];//当前价格,今天收盘价格
                String wPrice=splitvo[4];//当前价格,今天收盘价格

                //涨的股才统计
//                if(new BigDecimal(endprice).compareTo(new BigDecimal(nowPrice))==1){
//                    continue;
//                }

                String cjl=splitvo[8];
                //数据放入map里面
                CodeCjl codeCjl=new CodeCjl();
                codeCjl.setCode( codeStr.substring(codeStr.length() - 8));
                codeCjl.setHPrice(new BigDecimal(nowPrice));
                codeCjl.setHCjl(new BigDecimal(cjl));
                codeCjl.setZPrice(new BigDecimal(endprice));
                codeCjl.setWPrice(new BigDecimal(wPrice));
                codeCjls.add(codeCjl);
            }

            keyToken++;
        }
        return  codeCjls;
    }

    /**
     * 提示规则
     * @return
     */
    @Override
    public synchronized void hint(List<CodeCjl> lists, String type) {

        if(CollectionUtils.isEmpty(lists)){
            return ;
        }
        List<HintShares> ydList=new ArrayList<>();
        List<HintShares> hintShares=new ArrayList<>();
        order=0;
        for (CodeCjl codeCjl : lists) {
            try {
                //日涨幅判断
                HintShares getrzf = this.getrzf(codeCjl);
                if(null!=getrzf){
                    getrzf.setTsTime(DateUtil.getLongByCurrTime());
                    hintShares.add(getrzf);
                }
                //异动和关注的股
                HintShares getyd = this.getgz(codeCjl);
                if(null!=getyd){
                    ydList.add(getyd);
                }
            }catch (Exception e){
                e.printStackTrace();
            }
        }

        if(!CollectionUtils.isEmpty(hintShares)){
            hintSharesService.insertBatch(hintShares);
        }

        //计算分时均线
        this.getMavg();
        sendDingDing(ydList,"异动");

    }



    /**
     * 日涨幅提示
     * @param codeCjl
     */
    @Override
    public  HintShares getrzf(CodeCjl codeCjl) {
        CodeCjl vo1 = SharesConstan.CODE_MAP.get(codeCjl.getCode());
        if(null==vo1){
            return null;
        }
        boolean flag=true;
        //判断周涨幅是否大于0
        SharesDetail sharesDetail = SharesConstan.CODE_DETAIL_MAP.get(codeCjl.getCode());
        if(null==sharesDetail){
            return null;
        }
        String zkPrice = sharesDetail.getZkPrice();//周开盘价
        String ykPrice = sharesDetail.getYkPrice();//月开盘价

        BigDecimal bzzf=new BigDecimal(0);
        if(!StringUtil.isEmpty(zkPrice)){
            bzzf = MeUtils.calculateTrend(codeCjl.getHPrice().toString(), zkPrice);
        }
        BigDecimal byzf=new BigDecimal(0);
        if(!StringUtil.isEmpty(ykPrice)){
            byzf = MeUtils.calculateTrend(codeCjl.getHPrice().toString(), ykPrice);
        }

        if(byzf.compareTo(new BigDecimal(0))==-1){   //提示周涨幅为负
            flag=false;
        }
        if(bzzf.compareTo(new BigDecimal(0))==-1){ //提示周涨幅为负
            flag=false;
        }

        BigDecimal zPrice = vo1.getZPrice();
        BigDecimal zf = MeUtils.calculateTrend(codeCjl.getHPrice().toString(), zPrice.toString());

        HintShares hSharesVo = SharesConstan.INFORM_SHARES_MAP.get(codeCjl.getCode());
        BigDecimal maxzf = vo1.getMaxzf();//最近7天的最大涨幅
        if(null== maxzf){
            return  null;
        }
        if(!StringUtil.isEmpty(vo1.getType())){//最近股东大幅度减少的，和特别关注的，百分之3提示
            if(SharesConstan.GD.equals(vo1.getType())||SharesConstan.GZ.equals(vo1.getType())){//股东提示
                maxzf=new BigDecimal(0.03);
            }
        }
        if(null==hSharesVo){
            if(zf.compareTo(maxzf)==1){
                HintShares hintShares=new HintShares();

                BigDecimal wPrice = codeCjl.getWPrice();
                //如果高点是整点，00.50就显示出来,记录最高点整点有几个
                if(null!=wPrice){
                    String wpStr = wPrice.toString();
                    if(wpStr.contains(".50")||wpStr.contains(".00")){
                        Set<String> hType = hintShares.getHType();
                        if(!CollectionUtils.isEmpty(hType)){
                            hType.add(wpStr);
                            hintShares.setHType(hType);
                        }else{
                            Set<String> hTypeVo=new HashSet<>();
                            hTypeVo.add(wpStr);
                            hintShares.setHType(hType);
                        }
                    }
                }

                hintShares.setIndex(vo1.getIndex());
                hintShares.setCode(vo1.getCode());
                hintShares.setName(vo1.getName());
                hintShares.setTsprice(codeCjl.getHPrice());
                hintShares.setTime(DateUtil.getDate_yyyyMMdd());
                hintShares.setKeepTotal(1);
                hintShares.setKeepNum(1);
                hintShares.setNewPrice(codeCjl.getHPrice());
                String s = MeUtils.calculateTrend(codeCjl.getHPrice().toString()
                        , codeCjl.getZPrice().toString()).toString();
                hintShares.setTsZdf(MeUtils.getPercent(s));
                hintShares.setTsOrder(SharesConstan.ORDERINT++);
                if(flag){
                    hintShares.setAsorder(SharesConstan.ASORDERINT++);
                }else{
                    hintShares.setAsorder(0);
                }
                SharesConstan.INFORM_SHARES_MAP.put(codeCjl.getCode(), hintShares);
                Map<String, String> backStr = this.getBackStr(codeCjl);
                hintShares.setZback(backStr.get("zback"));//周风险
                hintShares.setYback(backStr.get("yback"));//月风险
                hintShares.setNewZdf(MeUtils.getPercent(zf.toString()));
                hintShares.setHPrice(wPrice);
                //最近异动
                HintShares vo = SharesConstan.HI_HINTSHARES_MAP.get(codeCjl.getCode());
                if(null!=vo){
                    hintShares.setYd(SharesConstan.YD_INT);
                }
                return hintShares;
            }
        }else {
            BigDecimal wPrice = codeCjl.getWPrice();
            //如果高点是整点，00.50就显示出来,记录最高点整点有几个
            if(null!=wPrice){
                String wpStr = wPrice.toString();
                if(wpStr.contains(".50")||wpStr.contains(".00")){
                    Set<String> hType = hSharesVo.getHType();
                    if(!CollectionUtils.isEmpty(hType)){
                        hType.add(wpStr);
                        hSharesVo.setHType(hType);
                    }else{
                        Set<String> hTypeVo=new HashSet<>();
                        hTypeVo.add(wpStr);
                        hSharesVo.setHType(hType);
                    }
                }
            }
            String s = MeUtils.calculateTrend(hSharesVo.getTsprice().toString()
                    , codeCjl.getZPrice().toString()).toString();
            hSharesVo.setTsZdf(MeUtils.getPercent(s));
            Map<String, String> backStr = this.getBackStr(codeCjl);
            hSharesVo.setZback(backStr.get("zback"));//周风险
            hSharesVo.setYback(backStr.get("yback"));//月风险
            hSharesVo.setNewZdf(MeUtils.getPercent(zf.toString()));
            hSharesVo.setNewPrice(codeCjl.getHPrice());//最新价格
            hSharesVo.setHPrice(wPrice);//
            Integer keepNum = hSharesVo.getKeepNum();
            Integer keepTotal = hSharesVo.getKeepTotal();
            if(zf.compareTo(maxzf)==1){
                hSharesVo.setKeepNum(keepNum+1);
                if(keepNum>=keepTotal){
                    hSharesVo.setKeepTotal(keepNum+1);
                }
            }else{
                if(keepNum>0){
                    hSharesVo.setKeepNum(keepNum-1);
                }
            }
        }
        return  null;
    }
    /**
     * 获取周涨幅数据
     * @param codeCjl
     * @return
     */
    @Override
    public Map<String,String> getBackStr(CodeCjl codeCjl) {
        CodeCjl vo1 = SharesConstan.CODE_MAP.get(codeCjl.getCode());
        StringBuffer zhsb=new StringBuffer(vo1.getZzf());

        String zback="";
        String yback="";
        if(!StringUtil.isEmpty(vo1.getZyback())){
            BigDecimal zbig = MeUtils.calculateTrend(codeCjl.getHPrice().toString()
                    , vo1.getZyback().split("-")[0]);
            BigDecimal ybig = MeUtils.calculateTrend(codeCjl.getHPrice().toString()
                    , vo1.getZyback().split("-")[1]);
            zback=MeUtils.getPercent(zbig.toEngineeringString());
            yback=MeUtils.getPercent(ybig.toEngineeringString());
        }
        Map<String,String> map=new HashMap<>();
        map.put("zback",zback);
        map.put("yback",yback);
        return map;
    }

    /**
     * 获取所有数据
     * @param parse
     * @param szorsh
     * @param name
     * @return
     */
    @Override
    public List<CodeCjl> getPriceList(List<Object> parse, String szorsh, String name) {

        if(CollectionUtils.isEmpty(parse)){
            return null;
        }

        List<CodeCjl> codeCjls=new ArrayList<>();
        for (Object o : parse) {
            CodeCjl codeCjl=new CodeCjl();
            String[] splito = o.toString().split(",");
            BigDecimal zcjl = new BigDecimal(splito[5]);
            BigDecimal spj = new BigDecimal(splito[2]);//收盘价
            BigDecimal kpj = new BigDecimal(splito[1]);//开盘价
            codeCjl.setTime(splito[0]);
            codeCjl.setZPrice(spj);
            codeCjl.setCode(szorsh);
            codeCjl.setName(name);

            codeCjls.add(codeCjl);
        }
        return  codeCjls;
    }



    private HintShares getgz(CodeCjl codeCjl) {

        HintShares dvo=null ;
        String code = codeCjl.getCode();
        //最近异动的
        SharesDetail voShares = SharesConstan.HI_SHARES_MAP.get(code);//详细数据
        CodeCjl vo = SharesConstan.CODE_MAP.get(codeCjl.getCode());//昨天的数据
        if(null!=voShares&&null!=vo){
            BigDecimal zPrice = vo.getZPrice();
            BigDecimal zf = MeUtils.calculateTrend(codeCjl.getHPrice().toString(), zPrice.toString());//当前涨幅

            HintShares hintShares=new HintShares();
            hintShares.setCode(vo.getCode());
            hintShares.setName(vo.getName());
            hintShares.setTsprice(codeCjl.getHPrice());
            hintShares.setTime(DateUtil.getDate_yyyyMMdd());
            hintShares.setKeepTotal(1);
            hintShares.setKeepNum(1);
            hintShares.setTsOrder(order++);
            hintShares.setId(hintShares.getTsOrder());
            hintShares.setNewPrice(codeCjl.getHPrice());
            String s = MeUtils.calculateTrend(codeCjl.getHPrice().toString()
                    , codeCjl.getZPrice().toString()).toString();
            hintShares.setTsZdf(MeUtils.getPercent(s));
            Map<String, String> backStr = this.getBackStr(codeCjl);
            hintShares.setZback(backStr.get("zback"));//周风险
            hintShares.setYback(backStr.get("yback"));//月风险
            hintShares.setNewZdf(MeUtils.getPercent(zf.toString()));
            hintShares.setNewPrice(codeCjl.getHPrice());//最新价格
            hintShares.setTsZdf(MeUtils.getPercent(s));

            Long infrom = SharesConstan.YD_MAP.get(hintShares.getCode());
            if(null==infrom&&zf.compareTo(new BigDecimal("0.049"))==1){
                //进行通知，只通知一次
                dvo=hintShares;
                SharesConstan.YD_MAP.put(hintShares.getCode(),DateUtil.getLongByCurrTime());
            }
            //添加到异动的map
            SharesConstan.HI_HINTSHARES_MAP.put(hintShares.getCode(),hintShares);

        }
        if(null==dvo){
            return null;
        }else{
            return  dvo;
        }

//        //关注的
//        SharesDetail toShares = SharesConstan.GZ_SHARES_MAP.get(code);
//        CodeCjl to = SharesConstan.CODE_MAP.get(codeCjl.getCode());//昨天的数据
//        if(null!=toShares&&null!=to){
//            //添加到关注的map
//            BigDecimal zPrice = vo.getZPrice();
//            BigDecimal zf = MeUtils.calculateTrend(codeCjl.getHPrice().toString(), zPrice.toString());//当前涨幅
//
//            HintShares hintShares=new HintShares();
//            hintShares.setCode(vo.getCode());
//            hintShares.setName(vo.getName());
//            hintShares.setTsprice(codeCjl.getHPrice());
//            hintShares.setTime(DateUtil.getDate_yyyyMMdd());
//            hintShares.setKeepTotal(1);
//            hintShares.setKeepNum(1);
//            hintShares.setNewPrice(codeCjl.getHPrice());
//            String s = MeUtils.calculateTrend(codeCjl.getHPrice().toString()
//                    , codeCjl.getZPrice().toString()).toString();
//            hintShares.setTsZdf(MeUtils.getPercent(s));
//            Map<String, String> backStr = this.getBackStr(codeCjl);
//            hintShares.setZback(backStr.get("zback"));//周风险
//            hintShares.setYback(backStr.get("yback"));//月风险
//            hintShares.setNewZdf(MeUtils.getPercent(zf.toString()));
//            hintShares.setNewPrice(codeCjl.getHPrice());//最新价格
//            hintShares.setTsZdf(MeUtils.getPercent(s));
//            //添加到异动的map
//            SharesConstan.GZ_HINTSHARES_MAP.put(hintShares.getCode(),hintShares);
//        }


    }

    private synchronized void sendDingDing(List<HintShares> hintSharesList, String title) {
        if(CollectionUtils.isEmpty(hintSharesList)){
            return ;
        }
        try {
            //钉钉机器人地址（配置机器人的webhook）
            String dingUrl = "https://oapi.dingtalk.com/robot/send?access_token=26bef694851730b4480524fa4f95ac913f40eeeb9975bef184df5cb5682e9f83";
            //是否通知所有人
            boolean isAtAll = true;
            //通知具体人的手机号码列表
            List<String> mobileList = new ArrayList<>();
            mobileList.add("18285152065");
            //组装请求内容
            String reqStr = buildReqStr(hintSharesList, isAtAll, mobileList,title);
            //推送消息（http请求）
            String result = HttpUtil.postJson(dingUrl, reqStr);
            System.out.println("result == " + result);
        }catch (Exception e){
            e.printStackTrace();

        }

    }

    private   String buildReqStr(List<HintShares> hintShares, boolean isAtAll, List<String> mobileList,
                                      String title) {

        StringBuffer sb=new StringBuffer();
        List<SharesInform> sharesInforms=new ArrayList<>();
        for (HintShares vo : hintShares) {

            String zsf= "sz/"+vo.getCode()+"_f_"+DateUtil.getLongByCurrTime()+".jpg";;
            String zsr= "sz/"+vo.getCode()+"_r_"+DateUtil.getLongByCurrTime()+".jpg";;

            //上传图片
            AliyunUtils.UploadImg(zsf,vo.getCode(),SharesConstan.FS);
            AliyunUtils.UploadImg(zsr,vo.getCode(),SharesConstan.DAY);

            sb.append(title+"_"+"["+vo.getName()+"](http://124.220.197.73:9200/shares?id_code="+vo.getCode()+")"+"_排序_"+vo.getAsorder()
                    +"\n"+ "![]("+"https://andi159753.oss-cn-hangzhou.aliyuncs.com/"+zsf+")"+"\n"
                    +"![]("+"https://andi159753.oss-cn-hangzhou.aliyuncs.com/"+zsr+")"+"\n" );
            List<String> voList=new ArrayList<>();
            voList.add(zsf);
            voList.add(zsr);
            for (String name : voList) {
                SharesInform sharesInform = new SharesInform();
                sharesInform.setName(vo.getName());
                sharesInform.setCode(vo.getCode());
                sharesInform.setPath(name);
                sharesInform.setTime(DateUtil.DEFAULT_DATE_FORMAT.format(new Date()));
                sharesInform.setType(title);
                sharesInforms.add(sharesInform);
            }
        }

        try {
            if(!CollectionUtils.isEmpty(sharesInforms)){
                sharesInformService.insertBatch(sharesInforms);
            }
        }catch (Exception e){
            System.out.println("保存通知数据出错");
        }

        Map<String, Object> atMap =new HashMap<>();
        //1.是否通知所有人
        atMap.put("isAtAll", isAtAll);
        //2.通知具体人的手机号码列表
        atMap.put("atMobiles", mobileList);

        Map<String, Object> reqMap = new HashMap<>();
        reqMap.put("msgtype", "markdown");
        Map<String,Object> pmap=new HashMap<>();
        pmap.put("text", sb.toString());
        pmap.put("title",title);
        reqMap.put("markdown", pmap);

        return JSON.toJSONString(reqMap);
    }

    /**
     * 神奇九转
     * @param parse
     * @param szorsh
     * @param name
     * @return
     */
    @Override
    public int nineTurn(List<Object> parse, String szorsh, String name) {
            try {
                List<Integer> indexs=new ArrayList<>();
                for (int i=1;i<20;i++){
                    String[] oEnd = parse.get(parse.size() - i).toString().split(",");
                    String[] oStart = parse.get(parse.size() - i-4).toString().split(",");
                    //收盘价>前第四天收盘价
                    if(new BigDecimal(oEnd[2]).compareTo(new BigDecimal(oStart[2]))==1){
                        indexs.add(1);
                        continue;
                    }
                    //收盘价<前第四天收盘价
                    if(new BigDecimal(oEnd[2]).compareTo(new BigDecimal(oStart[2]))==-1){
                        indexs.add(-1);
                        continue;
                    }
                }
                //判断是否有连续数字
                Integer integer = indexs.get(0);

                int index=0;
                for (Integer vo : indexs) {
                    if(vo==integer){
                        index++;
                    }else{
                        break;
                    }
                }
                if(integer==-1){
                    return  0-(index%9);
                }else{
                    return index%9;
                }
            }catch (Exception e){
                return  0;
            }

    }

    /**
     * 计算分时均线
     */
    @Override
    public void getMavg() {

        List<HintShares> zf10List=new ArrayList<>();
        List<HintShares> backList=new ArrayList<>();
        List<HintShares> jzList=new ArrayList<>();
        //成交额/成交量
        List<HintShares> hintSharesList=new ArrayList<>();
        List<HintShares> voSharesList=new ArrayList<>();
        for (String key : SharesConstan.INFORM_SHARES_MAP.keySet()) {

            voSharesList.add(SharesConstan.INFORM_SHARES_MAP.get(key));

            /**
             *      * 1、涨幅大于10的时候通知
             *      * 2、异动提示通知
             *      * 3、提示超过3次通知
             *      * 4、回撤通知
             *      *
             *      * 1、前25达到均线通知
             *      * 2、前25突破均线突破最高点通知
             *      * 3、异动达到均线通知
             *      * 4、异动突破最高点通知
             *      * 5、提示超过达到均线通知
             *      * 6、提示突破最高点通知
             */
            HintShares hintShares = SharesConstan.INFORM_SHARES_MAP.get(key);

            String newZdf = hintShares.getNewZdf();
            //5转以上的通知一次
            CodeCjl vo = SharesConstan.CODE_MAP.get(hintShares.getCode());//昨天的数据
            if(null!=vo){
                int index = vo.getIndex();
                hintShares.setIndex(index);
                if(index>4&&(new BigDecimal(newZdf).compareTo(new BigDecimal("5"))==1)){
                    Long aLong = SharesConstan.JZ_MAIL_MAP.get(hintShares.getCode());
                    if(null==aLong){
                        SharesConstan.JZ_MAIL_MAP.put(hintShares.getCode(),DateUtil.getLongByCurrTime());
                        jzList.add(hintShares);
                    }
                }
            }

            //大于10的时候提示1次
            if(new BigDecimal(newZdf).compareTo(new BigDecimal("10"))==1){
                    Long aLong = SharesConstan.ZF10_MAIL_MAP.get(hintShares.getCode());
                    if(null==aLong){
                        SharesConstan.ZF10_MAIL_MAP.put(hintShares.getCode(),DateUtil.getLongByCurrTime());
                        zf10List.add(hintShares);
                    }
            }
            int asorder = hintShares.getAsorder();
            //周回测，月回测小于20
            String zback = hintShares.getZback();
            String yback = hintShares.getYback();
            if(new BigDecimal(zback).compareTo(new BigDecimal(20))==-1
            &&new BigDecimal(yback).compareTo(new BigDecimal(20))==-1
            &&asorder<30&&asorder!=0){
                //通知
                    Long aLong = SharesConstan.BACK_MAIL_MAP.get(hintShares.getCode());
                    if(null==aLong){
                        SharesConstan.BACK_MAIL_MAP.put(hintShares.getCode(),DateUtil.getLongByCurrTime());
                        backList.add(hintShares);
                    }
            }
//            if(asorder<30&&asorder!=0){
//                hintSharesList.add(hintShares);
//                continue;
//            }
//            int yd = hintShares.getYd();
//            if(yd==1){
//                hintSharesList.add(hintShares);
//                continue;
//            }
//            //提示次数
//            List<HintShares> numList= SharesConstan.ALL_INFORM_SHARES_MAP.get(hintShares.getCode());
//            if(!CollectionUtils.isEmpty(numList)&&numList.size()>2){
//                hintSharesList.add(hintShares);
//                continue;
//            }
        }

        sendDingDing(zf10List,"涨幅突破10");
//        sendDingDing(backList,"周月回撤");

        for (HintShares hintShares : voSharesList) {
            String code = hintShares.getCode();
            Long aLong = SharesConstan.BACK_MAIL_MAP.get(code);
            if(null==aLong){
                continue;
            }
            String szorsh = hintShares.getCode();
            String substring = szorsh.substring(2);
            String url="";
            if(szorsh.contains("sz")){
                url="http://push2.eastmoney.com/api/qt/stock/get?ut=fa5fd1943c7b386f172d6893dbfba10b&invt=2&fltt=2" +
                        "&fields=f116,f168,f48,f47,f45,f44" +
                        "&secid=0." +substring+
                        "&cb=jQuery1124039477872536136194_"+new Date().getTime()
                        +"&_="+new Date().getTime();
            }

            if(szorsh.contains("sh")){
                url="http://push2.eastmoney.com/api/qt/stock/get?ut=fa5fd1943c7b386f172d6893dbfba10b&invt=2&fltt=2" +
                        "&fields=f116,f168,f48,f47,f44" +
                        "&secid=1." +substring+
                        "&cb=jQuery1124039477872536136194_"+new Date().getTime()
                        +"&_="+new Date().getTime();
            }

            try {
                HttpGet get=new HttpGet(url);
                CloseableHttpResponse execute = HttpClient5Utils.httpclient.execute(get);
                String result = EntityUtils.toString(execute.getEntity(), "UTF-8");
                int rIndex = result.indexOf("(");
                String resultStr = result.substring(rIndex + 1, result.length() - 2);
                JSONObject datas2 = JSONObject.parseObject(resultStr);
                String data = datas2.getString("data");
                JSONObject dataJson = JSONObject.parseObject(data);
                this.doEstimate(dataJson,hintShares);
            }catch (Exception e){

            }
        }
    }

    @Override
    public void sendBy163(HintShares hintShares,String title) throws Exception {
        String code = hintShares.getCode();
        String name = hintShares.getName();
        String imgcode=""   ;
        if(code.contains("sz")){
            imgcode= "0."+code.substring(2);
        }else{
            imgcode= "1."+code.substring(2);
        }
//        String fs = MeUtils.imgBase64("http://webquotepic.eastmoney.com/GetPic.aspx?nid="+imgcode+"&imageType=r");
        // 发送普通文本邮件
        mailUtil.sendMail(MailConstant.FROM_QQ, title+"_"+name+"_"+code+"_"+DateUtil.getDate_yyyyMMdd(),
                hintShares.getName() +"</br>"
//                        "<img src='data:image/png;base64,"+fs+"'> </br>"
                        +"<img src='http://webquotepic.eastmoney.com/GetPic.aspx?nid=?nid="+imgcode+"&imageType=r'> </br>"
                        +"<img src='http://webquoteklinepic.eastmoney.com/GetPic.aspx?nid="+imgcode+"&UnitWidth=-6&imageType=KXL&EF=&Formula=RSI&AT=1&&type=M5'> </br>"
                        +"<img src='http://webquoteklinepic.eastmoney.com/GetPic.aspx?nid="+imgcode+"&UnitWidth=-6&imageType=KXL&EF=&Formula=RSI&AT=1&&type='> </br>"
                        +"<img src='http://webquoteklinepic.eastmoney.com/GetPic.aspx?nid="+imgcode+"&UnitWidth=-6&imageType=KXL&EF=&Formula=RSI&AT=1&&type=W'> </br>"
                        +"<img src='http://webquoteklinepic.eastmoney.com/GetPic.aspx?nid="+imgcode+"&UnitWidth=-6&imageType=KXL&EF=&Formula=RSI&AT=1&&type=M'> </br>"
        );
        //通知后，重置最低价
        hintShares.setTsLowest(hintShares.getNewPrice());
    }

    /**
     * 获取数据
     * @param parse
     * @param szorsh
     * @param neme
     * @return
     */
    @Override
    public CodeCjl saveCjl(List<Object> parse, String szorsh, String neme) {
        if(CollectionUtils.isEmpty(parse)){
            return null;
        }
        CodeCjl codeCjl=new CodeCjl();
        Object o = parse.get(parse.size() -1);
        String[] splito = o.toString().split(",");
        BigDecimal zcjl = new BigDecimal(splito[5]);
        BigDecimal spj = new BigDecimal(splito[2]);//收盘价
        BigDecimal kpj = new BigDecimal(splito[1]);//开盘价

        codeCjl.setTime(splito[0]);
        if(spj.compareTo(kpj)==1){
            codeCjl.setStatus(SharesConstan.RED);
        }else{
            codeCjl.setStatus(SharesConstan.GREEN);
        }
        codeCjl.setZCjl(zcjl);
        codeCjl.setName(neme);
        codeCjl.setCode(szorsh);
        codeCjl.setZPrice(spj);

        //最近7天的涨跌幅，
        String zzf=getZzf(parse,codeCjl);
        if(!StringUtil.isEmpty(zzf)){
//            System.out.println(zzf);
            codeCjl.setZzf(zzf);
        }
        //近一周，和近一个月最大回撤
        String back=getbank(parse);
        if (!StringUtil.isEmpty(back)){
            codeCjl.setZyback(back);
        }else {
            return  null;
        }
        return  codeCjl;
//             22开始，倒数
//            vo.setD(split[0]);     //日期
//            vo.setO(new BigDecimal(split[1]));//开盘价
//            vo.setC(new BigDecimal(split[2]));//收盘价
//            vo.setH(new BigDecimal(split[3]));//最高价
//            vo.setL(new BigDecimal(split[4]));//最低价
//            vo.setV(new BigDecimal(split[5]));//成交量
    }

    /**
     * @param dataJson
     * @param hintShares
     */
    @Override
    public void doEstimate(JSONObject dataJson, HintShares hintShares) {
        List<HintShares> mavgList=new ArrayList<>();
        List<HintShares> hpriceList=new ArrayList<>();

        HintShares vo = SharesConstan.INFORM_SHARES_MAP.get(hintShares.getCode());
        if(null==vo){
            return;
        }
        String f48 = dataJson.getString("f48");//成交额
        String f47 = dataJson.getString("f47");//成交量
        String f44 = dataJson.getString("f44");//此时最高价

        //计算均线价格
        BigDecimal cje = new BigDecimal(f48);
        BigDecimal cjl = new BigDecimal(f47).multiply(new BigDecimal("100"));
        BigDecimal mavg = cje.divide(cjl, 2, BigDecimal.ROUND_HALF_UP);

        BigDecimal hPrice = vo.getHPrice();//上次最高价
        vo.setHPrice(new BigDecimal(f44));//现在最高价

        String lnOrGn="";
        vo.setMavg(mavg.toString());//均线
        if(vo.getNewPrice().compareTo(mavg)==1){
            lnOrGn=SharesConstan.GN;//价格大于均线
        }else{
            lnOrGn=SharesConstan.LN;//价格小于均线
            BigDecimal mavgGap = MeUtils.calculateTrend(vo.getMavg(),vo.getNewPrice().toString());
            if(mavgGap.compareTo(new BigDecimal(0.005))==1){//如果均线和价格相差大于1点)
                vo.setMavgSign(1);//持续多久还在均线以上的
            }
        }
        //判断均线突破，通知与否
        boolean flag=false;

//        int asorder = hintShares.getAsorder();
//        if(asorder<30){
//            flag=true;//小于30的
//        }
        int yd = hintShares.getYd();
        if(yd==1){//异动
            flag=true;
        }
        //提示次数
        List<HintShares> numList= SharesConstan.ALL_INFORM_SHARES_MAP.get(hintShares.getCode());
        if(!CollectionUtils.isEmpty(numList)&&numList.size()>2){
            flag=true;
        }

        Long zfLong = SharesConstan.ZF10_MAIL_MAP.get(hintShares.getCode());
        if(null!=zfLong){
            flag=true;
        }

        String gn = vo.getGn();
        if(!StringUtil.isEmpty(gn)&&!gn.equals(lnOrGn)
                &&lnOrGn.equals(SharesConstan.GN)){//突破均线，进行标记
            vo.setSetout("1");
            if(flag){
                try {
                    Long aLong = SharesConstan.MAVG_MAP.get(vo.getCode());
                    if(null==aLong){
                        SharesConstan.MAVG_MAP.put(vo.getCode(),DateUtil.getLongByCurrTime());
                        mavgList.add(hintShares);
                    }else{
                        Long longByCurrTime = DateUtil.getLongByCurrTime();
                        Long m= longByCurrTime-aLong;
                        if(m>600){
                            SharesConstan.MAVG_MAP.put(vo.getCode(),DateUtil.getLongByCurrTime());
                            mavgList.add(hintShares);
                        }
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }

        }
        vo.setGn(lnOrGn);
        if(!"1".equals(vo.getSetout())){
            return;
        }

        //提示后的最低价
        BigDecimal tsLowest = vo.getTsLowest();
        if (null==tsLowest){
            vo.setTsLowest(vo.getNewPrice());
            return;
        }else{
            if(vo.getNewPrice().compareTo(tsLowest)==-1){
                vo.setTsLowest(vo.getNewPrice());
            }
            //判断最低价和当前价格的差距
            BigDecimal calculateTrend = MeUtils.calculateTrend(vo.getNewPrice().toString(), tsLowest.toString());
            if(calculateTrend.compareTo(new BigDecimal("0.01"))==-1){
                return;
            }
        }
        //判断现在最高价，是否大于之前最高价
        if(vo.getHPrice().compareTo(hPrice)==1){
            try {
                //1分钟之内，就通知一次
                Long aLong = SharesConstan.HIGH_MAP.get(vo.getCode());
                Boolean falg=false;

                if(null!=aLong){
                    Long longByCurrTime = DateUtil.getLongByCurrTime();
                    Long m= longByCurrTime-aLong;
                    if(m>300){
                        falg=true;
                        SharesConstan.HIGH_MAP.put(vo.getCode(),DateUtil.getLongByCurrTime());
                    }
                }else{
                    falg=true;
                    SharesConstan.HIGH_MAP.put(vo.getCode(),DateUtil.getLongByCurrTime());
                }
                if(falg){
//                    this.sendDingDing(vo,"突破最高点通知");
                    hpriceList.add(vo);
                }
            }catch (Exception e){
                System.out.println("发送邮件失败 " + hintShares.getCode()+hintShares.getName());
            }
            vo.setSetout("0");
        }
        SharesConstan.INFORM_SHARES_MAP.put(hintShares.getCode(),vo);

        sendDingDing(mavgList,"均线突破");
        sendDingDing(hpriceList,"突破最高点");
    }

    /**
     * 获取实时数据
     * @return
     */
    @Override
    public List<CodeCjl> getCodeCjlsByTx(List<CodeCjl> list) {
        List<CodeCjl> codeCjls=new ArrayList<>();

        int listSize=list.size();
        int toIndex=50;
        int keyToken = 0;
        for(int i = 0;i<list.size();i+=50) {
            if(i+50>listSize){        //作用为toIndex最后没有50条数据则剩余几条newList中就装几条
                toIndex=listSize-i;
            }
            List<CodeCjl> newList = list.subList(i,i+toIndex);

            StringBuffer sb=new StringBuffer();
            if(!CollectionUtils.isEmpty(newList)){
                for (CodeCjl code : newList) {
                    sb.append(code.getCode()+",");
                }
            }

            String urlstring = sb.toString().substring(0, sb.toString().length() - 1);

            //发送请求得到数据
            String data="";
            try {
                HttpGet httpGet=new HttpGet("http://qt.gtimg.cn/q="+urlstring);
//                data = HttpUtil.sendGet("http://hq.sinajs.cn/list=" + urlstring, null);
//                HttpGet httpGet=new HttpUtil();
                CloseableHttpResponse execute = HttpClient5Utils.httpclient
                        .execute(httpGet);
                data = EntityUtils.toString(execute.getEntity());
            } catch (Exception e) {
                e.printStackTrace();
            }

            if(StringUtils.isEmpty(data)){
                return null;
            }
            String[] split = data.split(";\n");
//            格式数据：
//            v_sh600519="1~贵州茅台~600519~1981.00~1969.52~1960.00~5915~3143~2772~1981.00~17~1980.00~3~1979.89~1~1979.00~1~1978.01~2~1982.28~4~1982.67~2~1982.86~1~1982.88~10~1982.90~5~~20220121094330~11.48~0.58~1985.00~1951.01~1981.00/5915/1164216592~5915~116422~0.05~49.64~~1985.00~1951.01~1.73~24885.28~24885.28~14.27~2166.47~1772.57~3.42~2~1968.24~50.08~53.29~~~1.38~116421.6592~0.0000~0~ ~GP-A~-3.37~6.11~0.97~28.76~23.70~2608.59~1525.50~2.01~-6.56~8.52~1256197812~1256197812~4.35~-2.06~1256197812";
//            v_sz002307="51~北新路桥~002307~4.41~4.45~4.47~18713~8925~9789~4.41~763~4.40~1786~4.39~724~4.38~1341~4.37~1463~4.42~194~4.43~494~4.44~880~4.45~882~4.46~425~~20220121094330~-0.04~-0.90~4.47~4.40~4.41/18713/8282534~18713~828~0.18~90.91~~4.47~4.40~1.57~46.41~53.31~1.54~4.90~4.01~2.26~3202~4.43~97.62~96.78~~~0.63~828.2534~0.0000~0~ ~GP-A~3.28~2.56~0.00~1.69~0.16~5.50~4.03~-0.45~4.01~1.61~1052470312~1208921953~35.77~-6.57~1052470312";
//            v_sh600928="1~西安银行~600928~4.41~4.45~4.42~44067~17547~26520~4.41~72~4.40~2324~4.39~2201~4.38~4612~4.37~1661~4.42~1083~4.43~2590~4.44~1949~4.45~1374~4.46~1455~~20220121094330~-0.04~-0.90~4.43~4.39~4.41/44067/19423014~44067~1942~0.38~7.01~~4.43~4.39~0.90~50.96~196.00~0.73~4.90~4.01~4.28~2419~4.41~7.24~7.11~~~0.42~1942.3014~0.0000~0~ ~GP-A~2.56~1.85~4.31~10.46~0.83~5.32~4.24~0.92~2.08~1.15~1155635391~4444444375~12.52~-5.57~1155635391";

            for (String vo : split) {

                String[] splitvo = vo.split("=");
                String code = splitvo[0].replaceAll("v_", "");
                String[] detailList = splitvo[1].split("~");
                String name=detailList[1];
                String startPrice=detailList[5];//开盘价
                String endprice=detailList[4];//昨天收盘价
                String nowPrice=detailList[3];//当前价格,今天收盘价格
                String wPrice=detailList[33];//最高价
                String hxl= detailList[37];
                String cjl=detailList[6];//成交量
                //涨的股才统计
//                if(new BigDecimal(endprice).compareTo(new BigDecimal(nowPrice))==1){
//                    continue;
//                }
                //数据放入map里面
                CodeCjl codeCjl=new CodeCjl();
                codeCjl.setCode(code);
                codeCjl.setHPrice(new BigDecimal(nowPrice));
                codeCjl.setHCjl(new BigDecimal(cjl));
                codeCjl.setZPrice(new BigDecimal(endprice));
                codeCjl.setWPrice(new BigDecimal(wPrice));
                codeCjls.add(codeCjl);
            }

            keyToken++;
        }
        return  codeCjls;
    }

    /**
     * 近一周最低价，近一个月最低价
     * @param parse
     * @return
     */
    private String getbank(List<Object> parse) {

        List<Double> zList=new ArrayList<>();
        List<Double> yList=new ArrayList<>();
        if(parse.size()<30){
            return  null;
        }
        for(int i=1;i<30;i++){
            Object o = parse.get(parse.size()-i);
            String[] splito = o.toString().split(",");
            if(i<8){
                zList.add(new Double(splito[4]));
            }
            yList.add(new Double(splito[4]));
        }

        double zDouble = zList.stream().mapToDouble(Double::doubleValue).min().getAsDouble();
        double yDouble = yList.stream().mapToDouble(Double::doubleValue).min().getAsDouble();
        return zDouble+"-"+yDouble;
    }

    private String getZzf(List<Object> parse,CodeCjl codeCjl) {
        if(parse.size()<8){
            return  null;
        }
       String strh=new String();
       String strz=new String();

       List<Double> doubleList=new ArrayList<>();
       for (int i=1;i<8;i++){
           Object o = parse.get(parse.size()-i);
           Object o1 = parse.get(parse.size()-i-1);
           String[] splito = o.toString().split(",");
           String[] splito1 = o1.toString().split(",");
           //计算开盘到最高点的涨幅
           BigDecimal hzf = MeUtils.calculateTrend(splito[3], splito1[2]);
           doubleList.add(hzf.doubleValue());
           strh=MeUtils.getPercent(hzf.toString())+" "+strh;
           //计算开盘到收盘价的涨幅
           BigDecimal szf = MeUtils.calculateTrend(splito[2], splito1[2]);
//           str=(splito[0]+"="+MeUtils.getPercent(hzf.toString())+":"
//                   +MeUtils.getPercent(szf.toString())+"|")+str;
           strz=MeUtils.getPercent(szf.toString())+" "+strz;
       }

       if(!CollectionUtils.isEmpty(doubleList)){
           double zDouble = doubleList.stream().mapToDouble(Double::doubleValue).max().getAsDouble();
           if(zDouble>0.049){
               codeCjl.setMaxzf(new BigDecimal("0.049"));
           }else{
               codeCjl.setMaxzf(new BigDecimal(zDouble));
           }
       }else{
           codeCjl.setMaxzf(new BigDecimal("0.049"));
       }

        return strh+"="+strz;
    }

}
